/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "底层绘图/intern/Vulkan/buffer/Vk缓存.h"
#include "底层绘图/intern/Vulkan/线管/线管.h"
#include "面/面.h"

typedef struct {
	VkAccelerationStructureGeometryKHR			m_几何体;
	VkAccelerationStructureBuildRangeInfoKHR	m_顶点属性;
}S_几何体加速结构;



class C_Vk光追后端 : public S_光追后端 {
	
	//std::vector<VkAccelerationStructureGeometryKHR>			m_几何加速结构;
	std::vector<VkAccelerationStructureGeometryKHR>			m_顶层几何实例加速结构;
	//std::vector<VkAccelerationStructureBuildRangeInfoKHR*>	m_几何间隔;
	std::vector<VkAccelerationStructureBuildRangeInfoKHR*>	m_实例区间;
	std::vector<uint32>										m_几何图元数量;

	//VkAccelerationStructureBuildGeometryInfoKHR		m_加速结构绑定几何信息;
	VkAccelerationStructureBuildGeometryInfoKHR		m_加速结构绑定几何实例信息;

	//VkAccelerationStructureBuildSizesInfoKHR		m_加速结构绑定大小信息;
	VkAccelerationStructureBuildSizesInfoKHR		m_加速结构绑定实例大小信息;
	uint64 m_底层加速结构内存分配大小;


	VkPhysicalDeviceRayTracingPipelinePropertiesKHR				m_光追管线属性;

	std::vector<S_GPU内存块*>	m_加速结构布局;
	std::vector<S_GPU内存块*>	m_实例加速结构;
	std::vector<S_GPU内存块*>	m_顶层加速结构内存块;


	//S_板载缓存* m_底层加速结构缓存;
	S_板载缓存* m_顶层实例加速结构;
	S_板载缓存* m_底层暂存缓冲区;
	S_板载缓存* m_顶层暂存缓冲区;
	S_板载缓存* m_顶层暂存缓冲区_1;
	
	S_板载缓存* m_生成着色列表;
	S_板载缓存* m_忽略着色列表;
	S_板载缓存* m_相交着色列表;
	//S_板载缓存* m_AABB着色列表;
	S_板载缓存* m_回调着色列表;
	


	

	//std::vector<S_板载缓存*> m_底层加速结构缓存组;
	//std::map<uint32, S_板载缓存*> m_底层加速结构缓存组;
	std::map<uint32, S_板载缓存*> m_顶层加速结构缓存组;
	//VkDescriptorSet m_DescriptorSet;
	
	
	std::vector<VkDescriptorImageInfo> m_纹理信息;
	std::vector<VkDescriptorImageInfo> m_字符纹理信息;
	std::vector<VkDescriptorImageInfo> m_渲染纹理层;


	std::vector<VkAccelerationStructureKHR> m_顶层加速结构组;

public:
	C_Vk光追后端(S_设备环境& ctx);
	~C_Vk光追后端();

	
	std::vector<VkAccelerationStructureBuildRangeInfoKHR*> m_底层加速结构绑定信息;
	std::vector<VkAccelerationStructureBuildGeometryInfoKHR> m_加速结构绑定几何信息;
	std::vector<uint32> m_加速结构绑定大小信息;
	std::vector<S_GPU内存块> m_底层暂存缓冲区内存块;
	std::vector<S_Mesh*> m_底层加速结构网格;


	VkStridedDeviceAddressRegionKHR m_光追生成GPU地址;
	VkStridedDeviceAddressRegionKHR m_光追忽略GPU地址;
	//VkStridedDeviceAddressRegionKHR m_光追AABBGPU地址;
	VkStridedDeviceAddressRegionKHR m_光追相交GPU地址;
	VkStridedDeviceAddressRegionKHR m_光追回调GPU地址;


	void f_重置();
	void f_添加底层加速结构(S_Mesh* me, uint32 id, E_物体类型 ObType, uint32 实例材质位置);
	//void f_添加底层区域光网格加速结构(uint32 id, E_物体类型 ObType);
	void f_构建底层加速结构();

	void f_清除几何加速结构();
	void f_清除顶层加速构建写入描述();
	void f_分配底层加速结构数量(uint32 num);

	bool f_预分配实例变换(uint32 预分配);
	bool f_更新实例变换(S_GPU内存块& BLAS, mat3X4 mat, uint32 id, uint32 底层ASID, uint8 实例材质ID, uint8 mask, uint32 预分配);
	//bool f_更新实例变换(S_GPU内存块索引& BLAS, S_GPU内存块索引& 实例加速结构, Mat44f* mat, uint32 实例数量, uint32 底层ASID, uint8 实例材质ID, uint8 mask);
	void f_构建顶层加速结构(uint32 num);
	//void f_添加顶层加速结构(S_GPU内存块索引& TLAS, S_GPU内存块索引& 实例加速结构);
	//void f_构建顶层加速结构();
	void f_构建着色绑定列表();
	void f_构建GPU参数布局(S_纹理& tex);

	
	//void f_更新实例变换(mat3X4 mat, uint32 id);
	//void f_构建物体光追加速体(std::set<S_物体*>& obs);
	void f_构建BVH();
	void f_填充平行光参数(std::vector<S_LightParallel>& 平行光参数组);
	void f_Rander(GLSL_RenderFrame& 帧信息);
	void f_Rander(GLSL_RenderFrame& 帧信息, uint32 采样次数);


	void f_重构材质线管();
	void f_重载();

	void* f_get纹理(E_纹理分组类型 分组 = E_纹理分组类型::e_2D纹理) {
		switch (分组) {
			case E_纹理分组类型::e_2D纹理: {
				return m_纹理信息.data();
			}
			case E_纹理分组类型::e_字符纹理: {
				return m_字符纹理信息.data();
			}
			case E_纹理分组类型::e_渲染输出层: {
				return m_渲染纹理层.data();
			}
		}
		return nullptr;
	}
	uint16 f_get纹理数量(E_纹理分组类型 分组 = E_纹理分组类型::e_2D纹理) {
		switch (分组) {
			case E_纹理分组类型::e_2D纹理: {
				return m_纹理信息.size();
			}
			case E_纹理分组类型::e_字符纹理: {
				return m_字符纹理信息.size();
			}
			case E_纹理分组类型::e_渲染输出层: {
				return m_渲染纹理层.size();
			}
		}
		return 0;
	}
	void  f_add纹理(S_纹理* 纹理, uint32 loc, E_纹理分组类型 分组 = E_纹理分组类型::e_2D纹理);
	void  f_set纹理(S_纹理* 纹理, E_纹理分组类型 分组 = E_纹理分组类型::e_2D纹理);
	void  f_rem纹理(uint32 loc, E_纹理分组类型 分组 = E_纹理分组类型::e_2D纹理);

	void	f_刷新纹理GPU布局();
	void	f_更新纹理布局();
};



